package com.msb.mall.product.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.msb.common.constant.ProductConstant;
import com.msb.common.dto.MemberPrice;
import com.msb.common.dto.SkuHasStockDto;
import com.msb.common.dto.SkuReductionDto;
import com.msb.common.dto.SpuBoundsDto;
import com.msb.common.dto.es.SkuESModel;
import com.msb.common.utils.PageUtils;
import com.msb.common.utils.Query;
import com.msb.common.utils.R;
import com.msb.mall.product.dao.SpuInfoDao;
import com.msb.mall.product.entity.*;
import com.msb.mall.product.entity.vo.*;
import com.msb.mall.product.feign.CouponFeignService;
import com.msb.mall.product.feign.SearchFeignService;
import com.msb.mall.product.feign.WareFeignService;
import com.msb.mall.product.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;
    @Autowired
    SpuImagesService spuImagesService;
    @Autowired
    ProductAttrValueService productAttrValueService;
    @Autowired
    AttrService attrService;
    @Autowired
    SkuInfoService skuInfoService;
    @Autowired
    SkuImagesService skuImagesService;
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    CouponFeignService couponFeignService;
    @Autowired
    WareFeignService wareFeignService;
    @Autowired
    SearchFeignService searchFeignService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    BrandService brandService;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 保存商品信息的商品信息
     * @param vo 商品信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSpuInfo(SpuInfoVo vo) {

        //1.保存spu的基本信息 pms_spu_info
        SpuInfoEntity spuInfo = new SpuInfoEntity();
        BeanUtils.copyProperties(vo,spuInfo);
        //创建时间和更新时间手动同步
        spuInfo.setCreateTime(new Date());
        spuInfo.setUpdateTime(new Date());
        //设置状态为新建
        spuInfo.setPublishStatus(0);
        this.save(spuInfo);
        //2.保存spu的详情信息 pms_spu_info_desc
        List<String> decrypts = vo.getDecript();
        SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
        descEntity.setSpuId(spuInfo.getId());
        descEntity.setDecript(String.join(",",decrypts));
        spuInfoDescService.save(descEntity);

        //3.保存图集信息 pms_spu_images
        List<String> images = vo.getImages();
        //将每个图片封装成一个SpuImagesEntity实体对象
        List<SpuImagesEntity> imagesEntities = images.stream().map((item) -> {
            SpuImagesEntity spuImage = new SpuImagesEntity();
            spuImage.setSpuId(spuInfo.getId());
            spuImage.setImgUrl(item);
            return spuImage;
        }).collect(Collectors.toList());
        spuImagesService.saveBatch(imagesEntities);

        //4.保存规格参数 pms_product_attr_value
        List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
        //对规格数据做对应的处理
        List<ProductAttrValueEntity> valueEntities = baseAttrs.stream().map((attr) -> {
            ProductAttrValueEntity attrValue = new ProductAttrValueEntity();
            //关联商品编号
            attrValue.setSpuId(spuInfo.getId());
            attrValue.setAttrId(attr.getAttrId());
            attrValue.setAttrValue(attr.getAttrValues());
            AttrEntity attrEntity = attrService.getById(attr.getAttrId());
            attrValue.setAttrName(attrEntity.getAttrName());
            attrValue.setQuickShow(attr.getShowDesc());
            return attrValue;
        }).collect(Collectors.toList());
        productAttrValueService.saveBatch(valueEntities);

        //5.保存当前的sku对应的所有的sku信息
        //5.1保存sku的基本信息 pms_sku_info
        List<Skus> skus = vo.getSkus();
        if(vo.getSkus() != null && !vo.getSkus().isEmpty()){
            skus.forEach((item) ->{
                SkuInfoEntity skuInfo = new SkuInfoEntity();
                BeanUtils.copyProperties(item,skuInfo);
                skuInfo.setBrandId(spuInfo.getBrandId());
                skuInfo.setCatalogId(spuInfo.getCatalogId());
                skuInfo.setSpuId(spuInfo.getId());
                skuInfo.setSaleCount(0L);
                List<Images> imagesList = item.getImages();
                String defaultImage = "";
                for (Images images1 :imagesList) {
                    if (images1.getDefaultImg() == 1) {
                        //表示是默认的图片
                        defaultImage = images1.getImgUrl();
                    }
                }
                skuInfo.setSkuDefaultImg(defaultImage);
                skuInfoService.save(skuInfo);
                //5.2保存sku的图片信息 pms_sku_image
                List<SkuImagesEntity> skuImagesEntities = imagesList.stream().map((img) -> {
                    SkuImagesEntity skuImages = new SkuImagesEntity();
                    skuImages.setImgUrl(img.getImgUrl());
                    skuImages.setSkuId(spuInfo.getId());
                    skuImages.setDefaultImg(img.getDefaultImg());
                    return skuImages;
                }).filter(img -> img.getDefaultImg() == 1).collect(Collectors.toList());//TODO 为空的图片不需要保存
                skuImagesService.saveBatch(skuImagesEntities);
                //5.3保存满减，折扣，会员价 mall_sms:sms_sku_ladder sms-full_reduction sms_member_price
                SkuReductionDto dto = new SkuReductionDto();
                BeanUtils.copyProperties(item,dto);
                dto.setSkuId(skuInfo.getSkuId());
                //设置会员价
                if(item.getMemberPrice() != null && !item.getMemberPrice().isEmpty()){
                    List<MemberPrice> memberPrices = item.getMemberPrice().stream().map((m) -> {
                        MemberPrice memberPrice = new MemberPrice();
                        BeanUtils.copyProperties(m, memberPrice);
                        return memberPrice;
                    }).collect(Collectors.toList());
                    dto.setMemberPrice(memberPrices);
                }
                R fullResponse = couponFeignService.saveFullReduction(dto);
                if(fullResponse.getCode() !=0 ){
                    log.error("调用Coupon服务处理，满减,折扣,会员价操作失败......");
                    throw new RuntimeException();
                }

                //5.4 sku的销售属性 pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();
                List<SkuSaleAttrValueEntity> sales = attrs.stream().map((sale) -> {
                    SkuSaleAttrValueEntity saleAttrValue = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(sale, saleAttrValue);
                    saleAttrValue.setSkuId(skuInfo.getSkuId());
                    return saleAttrValue;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(sales);
            });
        }
        //6.保存spu的积分信息：mall_sms:sms_spu_bounds
        Bounds bounds = vo.getBounds();
        SpuBoundsDto spuBounds = new SpuBoundsDto();
        BeanUtils.copyProperties(bounds,spuBounds);
        spuBounds.setSkuId(spuInfo.getId());
        R boundsResponse = couponFeignService.saveSpuBounds(spuBounds);
        if(boundsResponse.getCode() != 0 ){
            log.error("调用Coupon服务处理，满减,折扣,会员价操作失败......");
            throw new RuntimeException();
        }
    }

    /**
     * spu信息检索
     * 分页查询
     * @param params 查询条件
     * @return
     */
    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        //设置对应的检索条件
        //1.关键字查询
        String key = (String) params.get("key");
        if(StringUtils.isNotEmpty(key)){
            wrapper.and((w) -> {
                w.eq("id",key)
                        .or().like("spu_name",key)
                        .or().like("spu_description",key);
            });
        }
        String status = (String) params.get("status");
        if(StringUtils.isNotEmpty(status)){
            wrapper.eq("publish_status", status);
        }
        String catalogId = (String) params.get("catalogId");
        if(StringUtils.isNotEmpty(catalogId) && !"0".equalsIgnoreCase(catalogId)){
            wrapper.eq("catalog_id", catalogId);
        }
        String brandId = (String) params.get("brandId");
        if(StringUtils.isNotEmpty(brandId) && !"0".equalsIgnoreCase(brandId)){
            wrapper.eq("brand_id", brandId);
        }
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        //根据分页信息，在查询出类被名称和品牌名称
        List<SpuInfoVo> collect = page.getRecords().stream().map((spu) -> {
            Long cateLogId = spu.getCatalogId();
            CategoryEntity category = categoryService.getById(cateLogId);
            Long brandIds = spu.getBrandId();
            BrandEntity brand = brandService.getById(brandIds);
            SpuInfoVo spuInfoVo = new SpuInfoVo();
            BeanUtils.copyProperties(spu, spuInfoVo);
            spuInfoVo.setCatalogName(category.getName());
            spuInfoVo.setBrandName(brand.getName());
            return spuInfoVo;
        }).collect(Collectors.toList());
        IPage<SpuInfoVo> iPage = new Page<>();
        iPage.setRecords(collect);
        iPage.setPages(page.getPages());
        iPage.setCurrent(page.getCurrent());
        iPage.setSize(page.getSize());
        iPage.setTotal(page.getTotal());
        return new PageUtils(iPage);
    }

    /**
     * 实现商品上架 相关数据存储到 elasticsearch
     * @param spuId id
     * 1、根据spuId 查询相关信息
     *    封装到对应的对象中
     * 2、将封装的数据存储到ElasticSearch，调用mall-search远程接口
     * 3、更新spuId的状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void spuUp(Long spuId) {
        //1、根据spuId查询相关信息 封装到SkuESModel对象中
        //spuId找到对应的sku
        List<SkuInfoEntity> skus = skuInfoService.list(
                new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId)
        );
        //2、调用mall-search远程服务，将SkuESModel中的数据存储到es中
        //对应的规格参数 根据spuId 查询规格参数信息
        List<SkuESModel.Attrs> attrsModel = getAttrsModel(spuId);

        //需要根据skuId 获取对应的库存信息 ---远程调用
        Map<Long, Boolean> skuHasStockMap = getSkuHasStock(skus);
        List<SkuESModel> skuESModels = skus.stream().map(item -> {
            SkuESModel model = new SkuESModel();
            BeanUtils.copyProperties(item,model);
            model.setSubTitle(item.getSkuTitle());
            model.setSkuPrice(item.getPrice());
            model.setSkuImg(item.getSkuDefaultImg());
            //hasStock是否有库存
            if(skuHasStockMap == null){
                model.setHasStock(true);
            }else{
                model.setHasStock(skuHasStockMap.get(item.getSkuId()));
            }
            //hotScore 热度分 默认0
            model.setHotScore(0L);
            //品牌名称
            BrandEntity brand = brandService.getById(item.getBrandId());
            model.setBrandImg(brand.getLogo());
            model.setBrandName(brand.getName());
            //类型名称
            CategoryEntity category = categoryService.getById(item.getCatalogId());
            model.setCateLogName(category.getName());
            //需要存储的规格数据
            model.setAttrs(attrsModel);
            return model;
        }).collect(Collectors.toList());

        //將SkuESModel中的数据存储到es中
        R r = searchFeignService.productStatusUp(skuESModels);
        //3、更新spuId 状态
        //根据对应的状态更新商品状态
        log.info("----->es操作完成：{}",r.getCode());
        if(r.getCode() == 0){
            //远程调用成功 更新商品的状态为 上架
            baseMapper.updateSpuStatusUp(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
        }else{
            //远程调用失败
            log.error("调用es服务保存商品信息到es中操作失败......");
            throw new RuntimeException();
        }
    }

    @Override
    public List<OrderItemSpuInfoVo> getOrderItemSpuBySpuId(Long[] spuIds) {
        List<Long> collect = Arrays.stream(spuIds).collect(Collectors.toList());
        //根据spuId查询相关信息
        List<SpuInfoEntity> spuInfoEntities = this.baseMapper.selectBatchIds(collect);
        return spuInfoEntities.stream().map(item -> {
            OrderItemSpuInfoVo orderItemSpuInfoVo = new OrderItemSpuInfoVo();
            orderItemSpuInfoVo.setId(item.getId());
            orderItemSpuInfoVo.setSpuDescription(item.getSpuDescription());
            orderItemSpuInfoVo.setSpuName(item.getSpuName());
            SpuImagesEntity spuId = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>().eq("spu_id", item.getId()));
            orderItemSpuInfoVo.setImg(spuId.getImgUrl());
            orderItemSpuInfoVo.setWeight(item.getWeight());
            orderItemSpuInfoVo.setBrandId(item.getBrandId());
            BrandEntity brand = brandService.getById(item.getBrandId());
            orderItemSpuInfoVo.setBrandName(brand.getName());
            orderItemSpuInfoVo.setCatalogId(item.getCatalogId());
            CategoryEntity category = categoryService.getById(item.getCatalogId());
            orderItemSpuInfoVo.setCatalogName(category.getName());
            orderItemSpuInfoVo.setPublishStatus(item.getPublishStatus());
            orderItemSpuInfoVo.setSpuDescription(item.getSpuDescription());
            return orderItemSpuInfoVo;
        }).collect(Collectors.toList());
    }


    private Map<Long,Boolean> getSkuHasStock(List<SkuInfoEntity> skus) {

        if(skus == null || skus.isEmpty()){
            return null;
        }
        List<Long> collect = skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        try {
            List<SkuHasStockDto> skuHasStock = wareFeignService.getSkuHasStock(collect);
            return skuHasStock.stream().collect(Collectors.toMap(SkuHasStockDto::getSkuId, SkuHasStockDto::getHasStock));
        }catch (Exception e){
            log.error("调用Ware服务获取sku库存信息操作失败......");
            throw new RuntimeException();
        }
    }


    /**
     * //对应的规格参数 根据spuId 查询规格参数信息
     * @param spuId 根据spuId
     * @return 数据
     */
    private List<SkuESModel.Attrs> getAttrsModel(Long spuId) {
        //1、product_attr_value 相关的所有规格参数
        List<ProductAttrValueEntity> baseAttrs = productAttrValueService.list(
                new QueryWrapper<ProductAttrValueEntity>()
                        .eq("spu_id", spuId)
        );

        //2、attr  search_type 是否支持检索
        List<Long> attrIds = baseAttrs.stream()
                .map(ProductAttrValueEntity::getAttrId)
                .collect(Collectors.toList());
        //查询到所有可以检索的规格参数编号
        List<Long> searchAttrIds = attrService.list(
                new QueryWrapper<AttrEntity>().in("attr_id",attrIds)
                        .eq("search_type",1)
        ).stream().map(AttrEntity::getAttrId).collect(Collectors.toList());
        //baseAttrs 中根据检索的数据过滤
        return baseAttrs.stream()
                .filter(item -> searchAttrIds.contains(item.getAttrId()))
                .map(item -> {
                    SkuESModel.Attrs attrs = new SkuESModel.Attrs();
                    BeanUtils.copyProperties(item, attrs);
                    return attrs;
        }).collect(Collectors.toList());
    }

}
